#![allow(clippy::extra_unused_lifetimes)]

use std::fmt::Pointer;
use serde::{Deserialize, Serialize};
use rbatis;
use rbatis::{impl_insert, impl_update, impl_delete, impl_select};
use rbatis::rbdc::datetime::FastDateTime;


#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct User {
    pub id: Option<String>,
    pub username: Option<String>,
    pub password: Option<String>,
    pub email: Option<String>,
    pub created_at: Option<FastDateTime>,
}

rbatis::crud!(User{});

impl_select!(User{select_by_id(id:String) -> Option => "`where id = #{id} limit 1`"});
impl_select!(User{select_by_username(username:String) -> Option => "`where username = #{username} limit 1`"});
impl_select!(User{select_by_email(email:String) -> Option => "`where email = #{email} limit 1`"});
impl_update!(User{update_by_name(name:&str, id: String) => "`where id = #{id}`"});


impl User {
    pub fn from_details<Q: Into<String>, R: Into<String>, S: Into<String>,
        T: Into<String>>(user_id: Q, username: R, password: S, email: T)
        -> Self {
        User {
            id: Some(user_id.into()),
            username: Some(username.into()),
            password: Some(password.into()),
            email: Some(email.into()),
            created_at: Some(FastDateTime::now()),
        }
    }
}


#[derive(Debug, Deserialize, Clone)]
pub struct AuthData {
    pub username: String,
    pub password: String,
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct RegisterData {
    pub username: String,
    pub password: String,
    pub email: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct SlimUser {
    pub username: Option<String>,
}


impl From<User> for SlimUser {
    fn from(user: User) -> Self {
        SlimUser { username: Some(user.username.unwrap()) }
    }
}
